package com.zp.base.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zp.base.entity.serialNumberDict.SerialNumberDict;
import com.zp.base.entity.serialNumberDict.bo.SerialNumberDictBo;
import com.zp.base.entity.serialNumberDict.vo.SerialNumberDictVo;
import com.zp.base.service.serialNumberDict.ISerialNumberDictService;
import com.zp.common.core.constant.BaseConstants;
import com.zp.common.core.constant.SerialNumberConstants;
import com.zp.common.core.utils.DateUtils;
import com.zp.common.core.utils.StringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;


/**
 * @program: zp-backstage
 * @ClassName RequestNumUtils
 * @description: TODO 系统各种单号生成公共类
 * @NoArgsConstructor ： 生成一个无参数的构造方法
 * @AllArgsContructor： 会生成一个包含所有变量的构造方法，默认生成的方法是 public 的
 * @RequiredArgsConstructor： 会生成一个包含常量，和标识了NotNull的变量的构造方法。生成的构造方法是私有的private。（可能带参数也可能不带参数）
 * @author: zhangpeng
 * @create: 2023-07-07 16:09
 * @Version 1.0
 **/

@Component
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Service
public class SerialNumberUtils {

    private final static Date NEW_DATE = DateUtils.dateTime("yyyy-MM-dd", DateUtils.getDate());
    /**
     * 当前日期字符串 yyyyMMdd
     */
    private final static String NEW_DATE_STR = DateUtils.SerialDateTime("yyMMdd");
    public static SerialNumberUtils serialNumberUtils;
    @Resource
    private ISerialNumberDictService iSerialNumberDictService;

    public static SerialNumberDictVo getSerialInfo(String orgId, String serialNumberType) {
        SerialNumberDictBo serialNumberDictBo = new SerialNumberDictBo();
        serialNumberDictBo.setOrgId(orgId);
        serialNumberDictBo.setCurrentNewDate(NEW_DATE);
        SerialNumberDictVo serialNumberDictVo = serialNumberUtils.iSerialNumberDictService.queryOne(serialNumberDictBo);
        if (ObjectUtil.isNotNull(serialNumberDictVo)) {
            updateSerialNumbers(serialNumberDictVo, serialNumberType);
            return serialNumberDictVo;
        } else {
            SerialNumberDictBo bo = getSerialNumberDictBo(orgId);
            SerialNumberDictBo newSerialNum = serialNumberUtils.iSerialNumberDictService.insertByBo(bo);
            return BeanUtil.toBean(newSerialNum, SerialNumberDictVo.class);
        }
    }

    private static SerialNumberDictBo getSerialNumberDictBo(String orgId) {
        SerialNumberDictBo bo = new SerialNumberDictBo();
        bo.setClinicNo(1000);
        bo.setHospitalNo(1000);
        bo.setDrugImportNo(1000);
        bo.setDrugExportNo(1000);
        bo.setConsumablesImportNo(1000);
        bo.setConsumablesExportNo(1000);
        bo.setClinicExamNo(1000);
        bo.setClinicLabNo(1000);
        bo.setVisitLabNo(1000);
        bo.setVisitExamNo(1000);
        bo.setOutpTreatNo(1000);
        bo.setClinicPrescriptionNo(1000);
        bo.setVisitPrescriptionNo(1000);
        bo.setOutpFeesNo(1000);
        bo.setDrugInventoryNo(1000);
        bo.setPrepaymentNo(1000);
        bo.setCurrentNewDate(NEW_DATE);
        bo.setOrgId(orgId);
        return bo;
    }

    public static void updateSerialNumbers(SerialNumberDictVo serialNumberDictVo, String serialNumberType) {
        LambdaUpdateWrapper<SerialNumberDict> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        switch (serialNumberType) {
            case "clinic_no":
                // 门诊号
                serialNumberDictVo.setClinicNo(serialNumberDictVo.getClinicNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getClinicNo, serialNumberDictVo.getClinicNo());
                break;
            case "hospital_no":
                // 住院号
                serialNumberDictVo.setHospitalNo(serialNumberDictVo.getHospitalNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getHospitalNo, serialNumberDictVo.getHospitalNo());
                break;
            case "drug_import_no":
                // 药品入库
                serialNumberDictVo.setDrugImportNo(serialNumberDictVo.getDrugImportNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getDrugImportNo, serialNumberDictVo.getDrugImportNo());
                break;
            case "drug_export_no":
                // 药品出库
                serialNumberDictVo.setDrugExportNo(serialNumberDictVo.getDrugExportNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getDrugExportNo, serialNumberDictVo.getDrugExportNo());
                break;
            case "clinic_exam_no":
                // 门诊检查号
                serialNumberDictVo.setClinicExamNo(serialNumberDictVo.getClinicExamNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getClinicExamNo, serialNumberDictVo.getClinicExamNo());
                break;
            case "visit_exam_no":
                // 住院检查号
                serialNumberDictVo.setVisitExamNo(serialNumberDictVo.getVisitExamNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getVisitExamNo, serialNumberDictVo.getVisitExamNo());
                break;
            case "clinic_lab_no":
                // 门诊检验号
                serialNumberDictVo.setClinicLabNo(serialNumberDictVo.getClinicLabNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getClinicLabNo, serialNumberDictVo.getClinicLabNo());
                break;
            case "visit_lab_no":
                // 住院检验号
                serialNumberDictVo.setVisitLabNo(serialNumberDictVo.getVisitLabNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getVisitLabNo, serialNumberDictVo.getVisitLabNo());
                break;
            case "outp_treat_no":
                // 门诊诊疗项目
                serialNumberDictVo.setOutpTreatNo(serialNumberDictVo.getOutpTreatNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getOutpTreatNo, serialNumberDictVo.getOutpTreatNo());
                break;
            case "clinic_prescription_no":
                // 门诊处方号
                serialNumberDictVo.setClinicPrescriptionNo(serialNumberDictVo.getClinicPrescriptionNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getClinicPrescriptionNo, serialNumberDictVo.getClinicPrescriptionNo());
                break;
            case "visit_prescription_no":
                // 住院处方号
                serialNumberDictVo.setVisitPrescriptionNo(serialNumberDictVo.getVisitPrescriptionNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getVisitPrescriptionNo, serialNumberDictVo.getVisitPrescriptionNo());
                break;
            case "outp_fees_no":
                // 住院处方号
                serialNumberDictVo.setOutpFeesNo(serialNumberDictVo.getOutpFeesNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getOutpFeesNo, serialNumberDictVo.getOutpFeesNo());
                break;
            case "drug_inventory_no":
                // 药品盘点序号
                serialNumberDictVo.setDrugInventoryNo(serialNumberDictVo.getDrugInventoryNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getDrugInventoryNo, serialNumberDictVo.getDrugInventoryNo());
                break;
            case "prepayment_no":
                // 预交金收款号
                serialNumberDictVo.setPrepaymentNo(serialNumberDictVo.getPrepaymentNo() + 1);
                lambdaUpdateWrapper.set(SerialNumberDict::getPrepaymentNo, serialNumberDictVo.getPrepaymentNo());
                break;
            default:
                break;
        }
        lambdaUpdateWrapper.eq(SerialNumberDict::getCurrentNewDate, serialNumberDictVo.getCurrentNewDate())
                .eq(SerialNumberDict::getOrgId, serialNumberDictVo.getOrgId());
        serialNumberUtils.iSerialNumberDictService.updateSerialNumbers(lambdaUpdateWrapper);
    }

    /**
     * 获取药品入库序号
     *
     * @param orgId
     * @param prefix synchronized
     * @return
     */
    public static String generateDrugImportNo(String orgId, String prefix) {
        SerialNumberDictVo selectSerial = getSerialInfo(orgId, "drug_import_no");
        return SerialNumberConstants.DRUG_IMPORT_NO + prefix + NEW_DATE_STR + selectSerial.getDrugImportNo();
    }

    /**
     * 获取药品出库序号
     *
     * @param orgId
     * @param prefix synchronized
     * @return
     */
    public static String generateDrugExportNo(String orgId, String prefix) {
        SerialNumberDictVo selectSerial = getSerialInfo(orgId, "drug_export_no");
        return SerialNumberConstants.DRUG_EXPORT_NO + prefix + NEW_DATE_STR + selectSerial.getDrugExportNo();
    }

    /**
     * 获取门诊号
     *
     * @param orgId
     * @return
     */
    public static String generateClinicNo(String orgId) {
        SerialNumberDictVo selectSerial = getSerialInfo(orgId, "clinic_no");
        return SerialNumberConstants.CLINIC_NO + NEW_DATE_STR + selectSerial.getClinicNo();
    }

    /**
     * 获取住院号
     *
     * @param orgId
     * @return
     */
    public static String generateHospitalNo(String orgId) {
        SerialNumberDictVo selectSerial = getSerialInfo(orgId, "hospital_no");
        return SerialNumberConstants.HOSPITAL_NO + NEW_DATE_STR + selectSerial.getHospitalNo();
    }

    /**
     * 获取检查号
     *
     * @param type  住院、门诊类型
     * @param orgId 机构id
     * @return 序号
     */
    public static String generateExamNo(String type, String orgId) {
        if (StringUtils.equals(BaseConstants.IS_CLINIC, type)) {
            SerialNumberDictVo selectSerial = getSerialInfo(orgId, "clinic_exam_no");
            return SerialNumberConstants.CLINIC_EXAM_NO + NEW_DATE_STR + selectSerial.getClinicExamNo();
        } else if (StringUtils.equals(BaseConstants.IS_VISIT, type)) {
            SerialNumberDictVo selectSerial = getSerialInfo(orgId, "visit_exam_no");
            return SerialNumberConstants.VISIT_EXAM_NO + NEW_DATE_STR + selectSerial.getVisitExamNo();
        }
        return "1000";
    }

    /**
     * @param type 门诊、住院类型
     * @throws
     * @description 获取检验号
     * @author zhp
     * @time 2024/2/28 上午11:07
     */
    public static String generateLabNo(String type, String orgId) {
        if (StringUtils.equals(BaseConstants.IS_CLINIC, type)) {
            SerialNumberDictVo selectSerial = getSerialInfo(orgId, "clinic_lab_no");
            return SerialNumberConstants.CLINIC_LAB_NO + NEW_DATE_STR + selectSerial.getClinicLabNo();
        } else if (StringUtils.equals(BaseConstants.IS_VISIT, type)) {
            SerialNumberDictVo selectSerial = getSerialInfo(orgId, "visit_lab_no");
            return SerialNumberConstants.VISIT_LAB_NO + NEW_DATE_STR + selectSerial.getVisitLabNo();
        }
        return "1000";
    }

    /**
     * 获取门诊诊疗项目号
     *
     * @param orgId
     * @return
     */
    public static String generateOutpTreatNo(String orgId) {
        SerialNumberDictVo selectSerial = getSerialInfo(orgId, "outp_treat_no");
        return SerialNumberConstants.OUTP_TREAT_NO + NEW_DATE_STR + selectSerial.getOutpTreatNo();
    }

    /**
     * 获取处方号
     *
     * @param type  住院、门诊类型
     * @param orgId 机构id
     * @return 序号
     */
    public static String generatePrescriptionNo(String type, String orgId) {
        if (StringUtils.equals(BaseConstants.IS_CLINIC, type)) {
            SerialNumberDictVo selectSerial = getSerialInfo(orgId, "clinic_prescription_no");
            return SerialNumberConstants.CLINIC_PRESCRIPTION_NO + NEW_DATE_STR + selectSerial.getClinicPrescriptionNo();
        } else if (StringUtils.equals(BaseConstants.IS_VISIT, type)) {
            SerialNumberDictVo selectSerial = getSerialInfo(orgId, "visit_prescription_no");
            return SerialNumberConstants.VISIT_PRESCRIPTION_NO + NEW_DATE_STR + selectSerial.getVisitPrescriptionNo();
        }
        return "1000";
    }

    /**
     * 获取门诊收费号
     *
     * @param orgId
     * @return
     */
    public static String generateOutpFeesNo(String orgId) {
        SerialNumberDictVo selectSerial = getSerialInfo(orgId, "outp_fees_no");
        return SerialNumberConstants.OUTP_FEES_NO + NEW_DATE_STR + selectSerial.getOutpFeesNo();
    }

    /**
     * 药品盘点序号
     *
     * @param orgId
     * @return
     */
    public static String generateDrugInventoryNo(String orgId) {
        SerialNumberDictVo selectSerial = getSerialInfo(orgId, "drug_inventory_no");
        return SerialNumberConstants.DRUG_INVENTORY_NO + NEW_DATE_STR + selectSerial.getDrugInventoryNo();
    }

    /**
     * 预交金收款号
     *
     * @param orgId
     * @return
     */
    public static String generatePrepaymentNo(String orgId) {
        SerialNumberDictVo selectSerial = getSerialInfo(orgId, "prepayment_no");
        return SerialNumberConstants.PREPAYMENT_NO + NEW_DATE_STR + selectSerial.getPrepaymentNo();
    }

    @PostConstruct
    public void init() {
        serialNumberUtils = this;
        //第四步：调用mapper或service接口
        serialNumberUtils.iSerialNumberDictService = this.iSerialNumberDictService;
    }
}
